'''
Created on Sep 28, 2009

@author: pntruongan
'''

import math


class Transformation:

    @staticmethod
    def MultiplyMatrix(A=[], B=[]):
        #so cot cua A phai bang so Hang cua B
        if len(A[0]) != len(B):
            #print "matrix ", A, " \n multiply by matrix \n ", B, "\n is invalid" 
            return
        result = [[0]*len(B[0]) for i in range(len(A))]

        for i in range(len(B[0])): #cot doc, ma tran 2
            for j in range(len(A)): #hang ngang, ma tran 1
                for k in range(len(B)): #hang ngang ma tran 2
        #           result[j][i] = result[j][i] + A[j][k]*B[k][i]
                    result[j][i] = result[j][i] + A[j][k]*B[k][i]         
        
        return result
    @staticmethod
    def __PointToMatrix(point=[]):
        result = [[0.0] for i in range(3)]
        result[0][0] = point[0]
        result[1][0] = point[1]
        result[2][0] = 1.0
        return result
    @staticmethod
    def __MatrixToPoint(matrix):
        result = (matrix[0][0],matrix[1][0])
        
        return result
    @staticmethod
    def __getTranslateMatrix(movex, movey):
        transformMatrix = [[0.0]*3 for i in range(3)]
        transformMatrix[0][0] = 1.0
        transformMatrix[0][2] = movex
        transformMatrix[1][1] = 1.0
        transformMatrix[1][2] = movey
        transformMatrix[2][2] = 1.0

        return transformMatrix
    
    @staticmethod
    def __getCenterPoint(points):
        x = y = 0.0
        for p in points:
            x = x + p[0]
            y = y + p[1]
        
        x = x / len(points)
        y = y / len(points)
        return (x,y)
        
    @staticmethod
    def Translate(points, moveX, moveY):
        result =[]
        transformMatrix = Transformation.__getTranslateMatrix(moveX, moveY)
        
        for point in points:
            result.append( Transformation.__MatrixToPoint(
                                    Transformation.MultiplyMatrix(
                                        transformMatrix,Transformation.__PointToMatrix(point))))
            
        return result
    
    @staticmethod
    def __transform(points, transformMatrix, translate = False):
        result = []
        transToO = []
        transBack = []
        
        if translate:   
            center = Transformation.__getCenterPoint(points)
            #print center
            transToO = Transformation.__getTranslateMatrix(-center[0], -center[1])
            transBack = Transformation.__getTranslateMatrix(center[0], center[1])
        #print "Trans to O ", transToO, " trans back ", transBack
        
        if translate:
            transformMatrix = Transformation.MultiplyMatrix(transBack, transformMatrix)
            transformMatrix = Transformation.MultiplyMatrix( transformMatrix,  transToO)
        
        for point in points:
            
            result.append( Transformation.__MatrixToPoint(
                                    Transformation.MultiplyMatrix(
                                        transformMatrix,Transformation.__PointToMatrix(point))))
            '''
            if translate:
                new = Transformation.MultiplyMatrix(transToO, Transformation.__PointToMatrix(point))
                new = Transformation.MultiplyMatrix(transformMatrix, new)
                new = Transformation.MultiplyMatrix(transBack, new)
                rs = Transformation.__MatrixToPoint(new)
                result.append(rs)  
            '''
        return result
    
    @staticmethod
    def Scale(points, scaleX, scaleY, translate = False):
        transformMatrix = [[0]*3 for i in range(3)]
        
        transformMatrix[0][0] = scaleX
        transformMatrix[1][1] = scaleY
        transformMatrix[2][2] = 1
        
        return Transformation.__transform(points, transformMatrix, translate)
    @staticmethod
    def Rotate(points, angle, translate = False):
        result =[]
        transformMatrix = [[0]*3 for i in range(3)]
        
        #convert angle to radiant
        angle = angle*math.pi/180
        
        transformMatrix[0][0] = math.cos(angle)
        transformMatrix[0][1] = -math.sin(angle)
        transformMatrix[1][0] = math.sin(angle)
        transformMatrix[1][1] = math.cos(angle)
        transformMatrix[2][2] = 1

        return Transformation.__transform(points, transformMatrix, translate)
    @staticmethod
    def Shear(points, shearX, shearY, translate = False):
        result =[]
        transformMatrix = [[0]*3 for i in range(3)]
        
        transformMatrix[0][0] = 1
        transformMatrix[0][1] = shearX
        transformMatrix[1][1] = 1
        transformMatrix[1][0] = shearY
        transformMatrix[2][2] = 1
        
        return Transformation.__transform(points, transformMatrix, translate)    
        
    @staticmethod
    def roundMatrix(points):
        for i in points:
            i = (round(i[0]),round(i[1]))
        return points
    
    